package com.example.service

import java.io.*
import java.net.Socket

class SimpleFtpClient(
    private val host: String,
    private val port: Int = 21,
    private val timeout: Int,
    private val username: String,
    private val password: String,
) {
    private val controlSocket: Socket
    private val input: BufferedReader
    private val output: OutputStreamWriter

    init {
        println("host is $host, port is $port")
        controlSocket = Socket(host, port).apply { soTimeout = timeout }
        input = BufferedReader(InputStreamReader(controlSocket.getInputStream()))
        output = (OutputStreamWriter(controlSocket.getOutputStream()))
        println("controlSocket.isConnected is ${controlSocket.localAddress}")
        readResponse()
    }


    private fun readResponse(): String {
        val res = input.readLine()
        println(res)
        return res
    }

    fun login(): Boolean {
        sendCommand("USER $username")
        if (!readResponse().contains("331")) return false
        sendCommand("PASS $password")
        return readResponse().contains("230")
    }

    fun enterPasv() {
        sendCommand("PASV") // Enter Passive Mode
        val pasvResponse = readResponse()
    }

    fun listDirectory(remotePath: String = "."): List<String> {
        sendCommand("PASV") // Enter Passive Mode
        val pasvResponse = readResponse()
        val ip = pasvResponse.substringAfter("(").substringBefore(")").split(",").map { it.toInt() }
            .toIntArray()
        val port = (ip[4] shl 8) + ip[5]
        val host = "${ip[0]}.${ip[1]}.${ip[2]}.${ip[3]}"
        val dataSocket = Socket(host, port)
        sendCommand("LIST $remotePath")
        val reader = BufferedReader(InputStreamReader(dataSocket.getInputStream()))
        val files = mutableListOf<String>()
        reader.lines().forEach { files.add(it) }
        reader.close()
        dataSocket.close()
        return files
    }

    fun PWD(): List<String> {
        sendCommand("PASV") // Enter Passive Mode
        val pasvResponse = readResponse()
        val ip = pasvResponse.substringAfter("(").substringBefore(")").split(",").map { it.toInt() }
            .toIntArray()
        val port = (ip[4] shl 8) + ip[5]
        val host = "${ip[0]}.${ip[1]}.${ip[2]}.${ip[3]}"
        val dataSocket = Socket(host, port)
//        sendCommand("LIST $remotePath")
        val reader = BufferedReader(InputStreamReader(dataSocket.getInputStream()))
        val files = mutableListOf<String>()
        reader.lines().forEach { files.add(it) }
        reader.close()
        dataSocket.close()
        return files
    }

    fun downloadFile(remoteFilePath: String, localFilePath: String): Boolean {
        sendCommand("PASV")
        val pasvResponse = readResponse()
        val ip = pasvResponse.substringAfter("(").substringBefore(")").split(",").map { it.toInt() }
            .toIntArray()
        val port = (ip[4] shl 8) + ip[5]
        val dataSocket = Socket("${ip[0]}:${ip[1]}:${ip[2]}:${ip[3]}", port)
        sendCommand("RETR $remoteFilePath")
        val reader = BufferedReader(InputStreamReader(dataSocket.getInputStream()))
        val writer = BufferedWriter(OutputStreamWriter(FileOutputStream(localFilePath)))
        var line: String?
        while (reader.readLine().also { line = it } != null) {
            writer.write("$line\n")
        }
        reader.close()
        writer.close()
        dataSocket.close()
        return readResponse().contains("226")
    }

    fun quit() {
        sendCommand("QUIT")
        controlSocket.close()
    }

    private fun sendCommand(command: String) {
        output.write("$command\r\n")
        output.flush()
    }
}

fun main() {

    val ftpClient = SimpleFtpClient(
        host = "localhost",
        port = 21,
        username = "liangyuyini",
        password = "qwe",
        timeout = 5000
    )

    if (ftpClient.login()) {
        ftpClient.enterPasv()
        // 列出目录内容
        val files = ftpClient.listDirectory()
        println("目录内容:")
        files.forEach { println(it) }

        // 下载文件示例
        val remoteFile = "/path/to/remote/file.txt"
        val localFile = "downloaded_file.txt"
        if (ftpClient.downloadFile(remoteFile, localFile)) {
            println("文件下载成功: $localFile")
        } else {
            println("文件下载失败")
        }

        ftpClient.quit()
    } else {
        println("登录失败")
    }
}